package cn.flyinke.jc;


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.casbin.jcasbin.model.Assertion;
import org.casbin.jcasbin.model.Model;
import org.casbin.jcasbin.persist.Adapter;
import org.casbin.jcasbin.persist.Helper;
import org.casbin.jcasbin.util.Util;

import com.jfinal.kit.JsonKit;

public class FileTestAdapter implements Adapter{
	  private String filePath;

	    /**
	     * FileAdapter is the constructor for FileAdapter.
	     *
	     * @param filePath the path of the policy file.
	     */
	    public FileTestAdapter(String filePath) {
	        this.filePath = filePath;
	    }

	    /**
	     * loadPolicy loads all policy rules from the storage.
	     */
	    @Override
	    public void loadPolicy(Model model) {
	        if (filePath.equals("")) {
	            // throw new Error("invalid file path, file path cannot be empty");
	            return;
	        }

	        loadPolicyFile(model, Helper::loadPolicyLine);
	    }

	    /**
	     * savePolicy saves all policy rules to the storage.
	     */
	    @Override
	    public void savePolicy(Model model) {
	        if (filePath.equals("")) {
	            throw new Error("invalid file path, file path cannot be empty");
	        }

	        StringBuilder tmp = new StringBuilder();

	        for (Map.Entry<String, Assertion> entry : model.model.get("p").entrySet()) {
	            String ptype = entry.getKey();
	            Assertion ast = entry.getValue();

	            for (List<String> rule : ast.policy) {
	                tmp.append(ptype + ", ");
	                tmp.append(Util.arrayToString(rule));
	                tmp.append("\n");
	            }
	        }

	        for (Map.Entry<String, Assertion> entry : model.model.get("g").entrySet()) {
	            String ptype = entry.getKey();
	            Assertion ast = entry.getValue();

	            for (List<String> rule : ast.policy) {
	                tmp.append(ptype + ", ");
	                tmp.append(Util.arrayToString(rule));
	                tmp.append("\n");
	            }
	        }

	        savePolicyFile(tmp.toString().trim());
	    }


	    private void loadPolicyFile(Model model, Helper.loadPolicyLineHandler<String, Model> handler) {
	        FileInputStream fis;
	        try {
	            fis = new FileInputStream(filePath);
	        } catch (FileNotFoundException e) {
	            e.printStackTrace();
	            throw new Error("policy file not found");
	        }
	        BufferedReader br = new BufferedReader(new InputStreamReader(fis));

	        String line;
	        try {
	            while((line = br.readLine()) != null)
	            {
	            	System.out.println("line:"+line);
	            	loadPolicyLine(line, model);
	            }

	            fis.close();
	            br.close();
	        } catch (IOException e) {
	            e.printStackTrace();
	            throw new Error("IO error occurred");
	        }
	    }

	    private void savePolicyFile(String text) {
	        try {
	            FileOutputStream fos = new FileOutputStream(filePath);
	            fos.write(text.getBytes());
	            fos.close();
	        } catch (IOException e) {
	            e.printStackTrace();
	            throw new Error("IO error occurred");
	        }
	    }

	    /**
	     * addPolicy adds a policy rule to the storage.
	     */
	    @Override
	    public void addPolicy(String sec, String ptype, List<String> rule) {
	        throw new Error("not implemented");
	    }

	    /**
	     * removePolicy removes a policy rule from the storage.
	     */
	    @Override
	    public void removePolicy(String sec, String ptype, List<String> rule) {
	        throw new Error("not implemented");
	    }

	    /**
	     * removeFilteredPolicy removes policy rules that match the filter from the storage.
	     */
	    @Override
	    public void removeFilteredPolicy(String sec, String ptype, int fieldIndex, String... fieldValues) {
	        throw new Error("not implemented");
	    }
	    
	    
	    public static void loadPolicyLine(String line, Model model) {
	        if (line.equals("")) {
	            return;
	        }

	        if (line.charAt(0) == '#') {
	            return;
	        }

	        String[] tokens = line.split(", ");

	        String key = tokens[0];
	        String sec = key.substring(0, 1);
	        System.out.println("sec "+sec+",key " +key);
	        
	        List<String> list = Arrays.asList(Arrays.copyOfRange(tokens, 1, tokens.length));
	        System.out.println("list:"+JsonKit.toJson(list));
	        model.model.get(sec).get(key).policy.add(list);
	    }
}
